#include <errno.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <fcntl.h>  
#include "buffer.h"
#include "preforkserver.h"
#include "epolleventhandlerimpl.h"
#include "processor.cpp"

#define MAXBUF 1024
#define MAXFD 5000
#define MAXEVENTS 1024 
#define MAXLISTENFD 100 

const int SHMKEY = 1234556;
const int SUBPROCNUMB = 20;

int gport = 8001;
char * gip = NULL;
class PreForkServerImpl : public PreForkServer
{
public:
	PreForkServerImpl(int key, unsigned int aiSubprocnum):PreForkServer(key,aiSubprocnum){};
protected:
	virtual void ChildRun();
	virtual void BeforeChildRun();
	virtual void BeforeRun();
private:
	int listenfd;	
};

void PreForkServerImpl :: BeforeRun()
{
	int opt;
	struct sockaddr_in svraddr;
	bzero( &svraddr, sizeof(sockaddr_in) );
	
	svraddr.sin_family = AF_INET;
//	inet_aton( "127.0.0.1", &(svraddr.sin_addr) );
	svraddr.sin_addr.s_addr = INADDR_ANY;
	svraddr.sin_port = htons( gport );
	
	listenfd = socket( AF_INET, SOCK_STREAM, 0 );
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void*)&opt, sizeof(opt));

	assert ( 0 == bind( listenfd, (sockaddr *)&svraddr, sizeof(svraddr) ) );
	assert ( 0 == listen(listenfd,MAXLISTENFD) );
}


void PreForkServerImpl :: ChildRun()
{
	int nfds=0;
	int timeout = -1;
	
	EchoProcessor processor;
	EpollManager epolleventmng(listenfd,MAXFD,MAXEVENTS);
	assert ( epolleventmng.Init() == 0 );
	EpollEventHandlerImpl epolleventhandler( &epolleventmng, (Processor *)&processor); 

	for (;;)
	{
		int nfds = epolleventmng.WaitEvents(timeout);
		for ( int i=0; i<nfds; ++i )
		{
			epolleventhandler.Handle( epolleventmng.GetEventByPos(i) );
		}
	}
}

void PreForkServerImpl :: BeforeChildRun()
{
}

int main(int argc, char* argv[])
{ 
	int ret = -1;
	
	if (argc > 1)
		gport = atoi(argv[1]);
	PreForkServerImpl server(SHMKEY, SUBPROCNUMB);
	ret = server.Init();

	if (ret == 0)
	{
		server.Run();
	}
	else
	{
		printf("Server Init fail, ret %d\n",ret);
	}

	return 0;
}
